2013-03-26 14 views
5

Il problema che sto avendo è mantenere il testo inserito da un utente centrato verticalmente all'interno dell'elemento canvas. Ho creato un ambiente di test per provare a risolvere questo problema, che ho fornito in questo post insieme a un violino. Qui è il mio codice:Mantieni il testo centrato verticalmente su tela

HTML:

Enter Your Text: <br/> 
<textarea id="inputtextuser" onkeyup="inputtextgo()" name="Text">Enter Your</textarea> <br/> 
TextBaseline: 
<select id="inputtextbaseline" onchange="inputtextgo()";> 
    <option value="alphabetic">alphabetic</option> 
    <option value="top">top</option> 
    <option value="bottom">bottom</option> 
    <option value="middle">middle</option> 
    <option value="hanging">hanging</option> 
</select> <br/> 
<canvas id="canvas1" width="300px" height="200px" >Your browser does not support the HTML5 canvas tag.</canvas> <br/> 
<div id ="textheightentered"></div> 

CSS:

canvas { 
    border: solid 1px black; 
} 

JavaScript/jQuery:

//Declaring the Canvas 
var canvas1 = document.getElementById('canvas1'); 
context1 = canvas1.getContext('2d'); 

//running the function to update the canvas 
inputtextgo(); 

function inputtextgo() { 
    //Retrieving the text entered by the user 
    var inputtext = document.getElementById("inputtextuser").value; 
    //Calling the function to calculate the height on the text entered by the user 
    var textheight = fontheight(inputtext); 
    //retrieving the baseline selected by the user 
    var baseline = document.getElementById("inputtextbaseline").value; 
    //calculating the new y needed to center the text based on the height of the text 
    var y = 100 + textheight/2; 

    //Updating the canvas for the new text entered by the user 
    context1.clearRect(0, 0, 300, 200); 
    context1.font = "36px arial"; 
    context1.textBaseline = baseline; 
    context1.fillText (inputtext, 0, y); 

    //Drawing a line across the middle of the canvas for reference 
    context1.strokeStyle="red"; 
    context1.moveTo(5,100); 
    context1.lineTo(290,100); 
    context1.stroke(); 
    $("#textheightentered").text("Text Height: " + textheight); 
} 

function fontheight(text){ 

    var canvas=document.createElement("canvas"); 
    canvas.width = 1000; 
    canvas.height = 200; 
    var ctx=canvas.getContext("2d"); 

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

     // Draw the text in the specified area 
     ctx.save(); 
     ctx.clearRect(0,0, canvas.width, canvas.height); 
     ctx.baseline = "top"; 
     ctx.fillText(text, 0, 35); // 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; 
    } 
    ctx.font= "36px arial"; 
    var height = measureTextHeight(0, 0, canvas.width, canvas.height,text); 
    //return the height of the string 
    return height; 
} // end $(function(){}); 

JSFiddle: http://jsfiddle.net/grapien/R6DWN/3/

Il problema che sto avendo è che se l'utente inserisce una lettera minuscola "y", ad esempio, l'altezza del testo cambia e il testo non rimane al centro della tela. Ciò a causa del fatto che la correzione della linea di base eseguita nella variabile y dovrebbe differire in base al testo immesso (combinazione di caratteri maiuscoli e minuscoli) poiché il testo al di sotto della linea di base sta inclinando la correzione eseguita nella variabile y.

Questo è il punto in cui ho i miei problemi poiché vorrei mantenere il testo centrato in ogni momento all'interno dell'elemento canvas. L'unica cosa che posso pensare è di calcolare i pixel non vuoti sopra uno sotto il punto di riferimento della linea di testo. Quindi utilizzare la differenza dalla linea di base alle estremità del testo per spostare il testo al centro del testo. Non sono sicuro di come ti appresti a scrivere questo script o se è addirittura possibile. Ma questo è l'approccio migliore che ho trovato.

Se qualcuno ha qualche idea o guida, sarebbe molto apprezzato poiché lo sviluppo di un approccio per risolvere questo problema mi ha convinto.

+0

Grazie per aver apportato modifiche al mio post Matt, sembra che mi sia perso un paio di cose nella mia recensione. – grapien

risposta

0

Credo di aver risolto questa domanda usando la tecnica che ho affermato nella domanda. Ho creato una nuova funzione che calcola la quantità di carattere che si estende al di sotto della linea di base del testo inserito. Utilizzando una tecnica simile a ciò che è stato utilizzato per calcolare l'altezza. Io uso la linea di base alfabetica quindi calcolare i pixel che contengono il contenuto sopra questa linea di base. Vedi la funzione qui sotto.

function fontheight2(text){ 

    var canvas=document.createElement("canvas"); 
    canvas.width = 1000; 
    canvas.height = 200; 
    var ctx=canvas.getContext("2d"); 

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

     // Draw the text in the specified area 
     ctx.save(); 
     ctx.clearRect(0,0, canvas.width, canvas.height); 
     ctx.fillText(text, 0, 100); // 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 = 100, 
      c = 0; 

     // 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 99 - first; 
     } 

     // We screwed something up... What do you expect from free code? 
     return 0; 
    } 
    ctx.baseline = "Alphabetic"; 
    ctx.font= "36px arial"; 
    var height = measureTextHeight(0, 0, canvas.width, canvas.height,text); 
    //return the height of the string 
    return height; 
} // end $(function(){}); 

Da lì semplicemente utilizzare i seguenti cambiamenti a y per compensare il testo al centro:

var textheight = fontheight(inputtext); //Calculate Text Height 
var textheight2 = fontheight2(inputtext); //Calculate portion above the baseline 
var difference = textheight - textheight2; // Calculate the portion below the baseline 
var y = 100 - difference + textheight/2; // Adjust the y cordinate 

Questo compensa il y per regolare la porzione di testo che si trova sotto la base del testo . Ho aggiornato JSFiddle qui http://jsfiddle.net/grapien/R6DWN/6/.

0

Si può dare un'occhiata a questo link. Viene utilizzato un wrapper di testo.

+0

In realtà sto usando quel codice sulla mia pagina web, ma non è dinamico poiché tutte le variabili sono preimpostate dall'utente (es. Lineheight e y) e non sono calcolate al volo. Ho eliminato più porzioni di riga del codice in quanto non è necessario per risolvere il problema. Il vero problema è che non esiste una riga di testo basata sul testo inserito dall'utente, ma piuttosto sulla libreria di caratteri utilizzata. Ciò si traduce in un diverso offset in base a ciò che l'utente ha digitato. Il problema più grande è come calcolare questo offset in modo dinamico. – grapien

+0

Sì, stavo testando il tuo codice Fiddle e la linea di base del testo fluttua attorno ai 25 ~ 32. Come soluzione molto semplice, prenderei l'altezza della linea di "Yy" anziché il testo dell'utente. Quindi, avresti una linea di base solida che non cambierebbe.Non è molto elegante anche se –

+0

Sono riuscito a capire come testare dinamicamente il codice vedere la mia risposta qui sotto. Prende la stringa e calcola la porzione della stringa che si trova sotto la linea base calcolando la differenza. Posso quindi tenere conto di questa differenza nella variabile y per regolare la posizione del testo. – grapien

Problemi correlati